package com.yelobblog.yelobblog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yelobblog.yelobblog.common.exception.ApiException;
import com.yelobblog.yelobblog.common.exception.ErrorEnum;
import com.yelobblog.yelobblog.common.untils.RandomUtil;
import com.yelobblog.yelobblog.common.untils.ThreadLocalUtil;
import com.yelobblog.yelobblog.common.untils.jwt;
import com.yelobblog.yelobblog.domain.entity.user;
import com.yelobblog.yelobblog.mapper.userMapper;
import com.yelobblog.yelobblog.service.userService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.yelobblog.yelobblog.common.untils.EmailService;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class userServiceimpl extends ServiceImpl<userMapper,user> implements userService{
    @Resource
    private userMapper userMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private EmailService emailService;

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public String Login(String email, String password) {
        user user = userMapper.selectOne(new QueryWrapper<user>().eq("email", email));
        if (user == null) {
            throw new ApiException(ErrorEnum.USER_NOT_FOUND.getErrorCode(), ErrorEnum.USER_NOT_FOUND.getErrorMsg());
        }
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new ApiException(ErrorEnum.PASSWORD_ERROR.getErrorCode(), ErrorEnum.PASSWORD_ERROR.getErrorMsg());
        }
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        map.put("email", user.getEmail());
        map.put("role", user.getRole());
        return jwt.getToken(map);
    }
    @Override
    public Boolean Register(String email, String password, String code) {
        String TCode = (String) redisTemplate.opsForValue().get(email);
        if (TCode == null || !TCode.equals(code)) {
            throw new ApiException(ErrorEnum.CODE_ERROR.getErrorCode(), ErrorEnum.CODE_ERROR.getErrorMsg());
        }
        if (userMapper.selectOne(new QueryWrapper<user>().eq("email",email)) != null) {
            //邮箱已注册
            throw new ApiException(ErrorEnum.EMAIL_REGISTERED.getErrorCode(), ErrorEnum.EMAIL_REGISTERED.getErrorMsg());
        }
        user user = new user();
        user.setEmail(email);
        user.setNickName(email);
        user.setPassword(passwordEncoder.encode(password));
        userMapper.insert(user);
        return true;
    }
    @Override
    public void SendCode(String email) {
        String code = RandomUtil.randomInt();
        emailService.sendEmail(email, "验证码", "验证码为:" + code);
        redisTemplate.opsForValue().set(email, code, 60 * 5, TimeUnit.SECONDS);
    }
    @Override
    public user getSelfInfo() {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        return userMapper.selectById(userId);
    }

    @Override
    public user getUserInfo(Integer userId) {
        return userMapper.selectById(userId);
    }

    @Override
    public void updateUserInfo(user user) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        if(!userId.equals(user.getId())) {
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(), ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        userMapper.updateById(user);
    }

    @Override
    @Transactional
    public void follow(Integer followId) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        userMapper.follow(followId,userId);
        userMapper.addFollowCount(userId);
        userMapper.addFansCount(followId);
    }
    @Transactional
    @Override
    public void unfollow(Integer followId) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        userMapper.unFollow(followId,userId);
        userMapper.deleteFollowCount(userId);
        userMapper.deleteFansCount(followId);
    }
}
